#include "config.h"

#include <memory>

#include "log.h"
#include "utils.h"

namespace afcore {

CConfigMgr& CConfigMgr::Instance() {
  static CConfigMgr s_instance;
  return s_instance;
}

bool CConfigMgr::Load(std::string const& filename, std::vector<std::string> args, std::string& error, bool reload /*=false*/) {
  std::lock_guard<std::mutex> lock(config_mutex_);

  if (!reload) {
    filename_ = filename;
    args_ = std::move(args);
  }

  try {
    bpt::ptree full_tree;
    bpt::ini_parser::read_ini(filename_, full_tree);

    if (full_tree.empty()) {
      error = "empty file (" + filename_ + ")";
      return false;
    }

    // 因为每个文件只有一个section配置，所以这个地方就直接取值了
    config_ = full_tree.begin()->second;
  } catch (bpt::ini_parser::ini_parser_error const& e) {
    if (0 == e.line()) {
      error = e.message() + " (" + e.filename() + ")";
    } else {
      error = e.message() + " (" + e.filename() + ":" + std::to_string(e.line()) + ")";
    }
    return false;
  }

  return true;
}

bool CConfigMgr::Reload(std::string& error) {
  return Load({}, {}, error, true);
}

std::string const& CConfigMgr::GetFilename() {
  std::lock_guard<std::mutex> lock(config_mutex_);
  return filename_;
}

std::string_view CConfigMgr::GetFilenameView() {
  std::lock_guard<std::mutex> lock(config_mutex_);
  return std::string_view(filename_.data(), filename_.size());
}

std::vector<std::string> const& CConfigMgr::GetArguments() const {
  return args_;
}

std::vector<std::string> CConfigMgr::GetKeysByString(std::string const& name) {
  std::lock_guard<std::mutex> lock(config_mutex_);

  std::vector<std::string> keys;

  // first  keys
  // second data
  for (auto&& child : config_) {
    if (0 == child.first.compare(0, name.length(), name)) {
      keys.push_back(child.first);
    }
  }

  return keys;
}

// 通用模板函数
template<class T>
T CConfigMgr::GetValueDefault(std::string const& name, T def) const {
  try {
    return config_.get<T>(bpt::ptree::path_type(name, '/'));
  } catch (bpt::ptree_bad_path) {
    LOG_WARN("Missing name {} in config file {}, add \"{} = {}\" to this file",
      name.c_str(), filename_.c_str(), name.c_str(), std::to_string(def).c_str());

  } catch (bpt::ptree_bad_data) {
    LOG_ERROR("Bad value defined for name {} in config file {}, going to use {} instead",
      name.c_str(), filename_.c_str(), std::to_string(def).c_str());
  }

  return def;
}

// 默认值为string的全特化函数
//! @note 特化函数必须在首次使用前完成特例化，否则是编译不过的
template<>
std::string CConfigMgr::GetValueDefault<std::string>(std::string const& name, std::string def) const {
  try {
    return config_.get<std::string>(bpt::ptree::path_type(name, '/'));
  } catch (bpt::ptree_bad_path) {
    LOG_WARN("Missing name {} in config file {}, add \"{} = {}\" to this file",
      name.c_str(), filename_.c_str(), name.c_str(), def.c_str());
  } catch (bpt::ptree_bad_data) {
    LOG_ERROR("Bad value defined for name {} in config file {}, going to use {} instead",
      name.c_str(), filename_.c_str(), def.c_str());
  }

  return def;
}

std::string CConfigMgr::GetStringDefault(std::string const& name, const std::string& def) const {
  std::string val = GetValueDefault(name, def);
  val.erase(std::remove(val.begin(), val.end(), '"'), val.end());
  return val;
}

bool CConfigMgr::GetBoolDefault(std::string const& name, bool def) const {
  std::string val = GetValueDefault(name, std::string(def ? "1" : "0"));
  val.erase(std::remove(val.begin(), val.end(), '"'), val.end());
  return StringToBool(val);
}

int32_t CConfigMgr::GetIntDefault(std::string const& name, int32_t def) const {
  return GetValueDefault(name, def);
}

int64_t CConfigMgr::GetInt64Default(std::string const& name, int64_t def) const {
  return GetValueDefault(name, def);
}

float CConfigMgr::GetFloatDefault(std::string const& name, float def) const {
  return GetValueDefault(name, def);
}

} // !namespace afcore